#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
智能Word样式复制器 - 基于Pandoc的交互式样式管理工具
作者: MiniMax Agent
功能: 抽取Word文档样式并应用到目标文档
"""

import os
import sys
import subprocess
import json
import tempfile
import shutil
from pathlib import Path
from datetime import datetime
from typing import List, Dict, Any, Optional
import argparse
import logging

class WordStyleCopier:
    """智能Word样式复制器"""
    
    def __init__(self):
        """初始化样式复制器"""
        self.setup_logging()
        self.pandoc_path = self.find_pandoc()
        self.temp_dir = Path(tempfile.mkdtemp(prefix="word_style_copier_"))
        self.style_mapping = {}
        self.apply_results = {}
        
    def setup_logging(self):
        """设置日志"""
        logging.basicConfig(
            level=logging.INFO,
            format='%(asctime)s - %(levelname)s - %(message)s',
            handlers=[
                logging.FileHandler('word_style_copier.log'),
                logging.StreamHandler(sys.stdout)
            ]
        )
        self.logger = logging.getLogger(__name__)
    
    def find_pandoc(self) -> str:
        """查找Pandoc可执行文件"""
        pandoc_paths = ['pandoc', '/usr/bin/pandoc', '/usr/local/bin/pandoc']
        
        for path in pandoc_paths:
            try:
                result = subprocess.run([path, '--version'], 
                                      capture_output=True, text=True)
                if result.returncode == 0:
                    self.logger.info(f"找到Pandoc: {path}")
                    return path
            except FileNotFoundError:
                continue
        
        raise FileNotFoundError("未找到Pandoc，请先安装Pandoc")
    
    def extract_styles_from_docx(self, docx_path: str) -> Dict[str, Any]:
        """
        从Word文档中抽取样式信息，特别优化了表格和图片标题样式的提取
        
        Args:
            docx_path: Word文档路径
            
        Returns:
            抽取的样式信息字典
        """
        try:
            self.logger.info(f"开始抽取文档样式: {docx_path}")
            
            # 验证文件格式
            if not docx_path.lower().endswith('.docx'):
                error_msg = f"不支持的文件格式: {docx_path}。请使用.docx格式的文档。"
                self.logger.error(error_msg)
                raise ValueError(error_msg)
            
            # 验证文件是否存在
            if not os.path.exists(docx_path):
                error_msg = f"文件不存在: {docx_path}"
                self.logger.error(error_msg)
                raise FileNotFoundError(error_msg)
            
            # 转换为HTML以便分析样式，使用更好的选项保留样式
            html_output = self.temp_dir / f"styles_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
            
            # 创建媒体文件提取目录
            media_dir = self.temp_dir / 'media'
            media_dir.mkdir(exist_ok=True)
            
            cmd = [
                self.pandoc_path,
                docx_path,
                '-o', str(html_output),
                '--standalone',
                '--toc',  # 生成目录以提取标题样式
                '--extract-media', str(media_dir),  # 提取媒体文件以保持样式完整
                '--wrap=preserve',  # 保留换行以保持格式
                '--table-of-contents',  # 确保目录结构正确
                '--reference-doc', docx_path,  # 使用自身作为引用文档以完整保留样式
                '--mathml',  # 确保公式等特殊内容正确转换
                '--number-sections'  # 帮助保留章节编号样式
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True)
            if result.returncode != 0:
                raise Exception(f"Pandoc转换失败: {result.stderr}")
            
            # 读取HTML内容并提取样式
            styles = self.parse_styles_from_html(html_output)
            
            # 额外抽取文档格式信息
            doc_info = self.extract_docx_info(docx_path)
            styles['document_info'] = doc_info
            
            # 添加更详细的表格和图片标题样式提取
            import re
            from bs4 import BeautifulSoup
            
            # 重新解析HTML以提取表格和图片标题样式
            with open(html_output, 'r', encoding='utf-8') as f:
                content = f.read()
            
            soup = BeautifulSoup(content, 'html.parser')
            
            # 详细提取表格样式信息
            tables = soup.find_all('table')
            table_styles = []
            for table in tables:
                table_info = {
                    'class': table.get('class', []),
                    'id': table.get('id'),
                    'rows': len(table.find_all('tr')),
                    'style': table.get('style', '')
                }
                
                # 提取表格的CSS类和样式规则
                table_classes = table.get('class', [])
                for cls in table_classes:
                    # 尝试在CSS中找到对应的类样式
                    class_pattern = rf'\.{re.escape(cls)}\s*{{([^}}]+)}}'
                    for style_content in styles.get('css_styles', []):
                        matches = re.findall(class_pattern, style_content, re.DOTALL)
                        if matches:
                            if 'class_styles' not in table_info:
                                table_info['class_styles'] = []
                            table_info['class_styles'].extend(matches)
                
                # 提取表格内的表头样式
                thead = table.find('thead')
                if thead:
                    th_elements = thead.find_all('th')
                    if th_elements:
                        table_info['header_style'] = th_elements[0].get('style', '')
                
                # 提取表格内的单元格样式
                tbody = table.find('tbody')
                if tbody:
                    td_elements = tbody.find_all('td')
                    if td_elements:
                        table_info['cell_style'] = td_elements[0].get('style', '')
                
                table_styles.append(table_info)
            
            # 详细提取图片和图片标题样式信息
            images = soup.find_all('img')
            image_styles = []
            figcaptions = []
            
            # 查找figure元素（通常包含图片和标题）
            figures = soup.find_all('figure')
            for figure in figures:
                fig_img = figure.find('img')
                fig_cap = figure.find('figcaption')
                
                if fig_img:
                    img_info = {
                        'src': fig_img.get('src'),
                        'alt': fig_img.get('alt', ''),
                        'width': fig_img.get('width'),
                        'height': fig_img.get('height'),
                        'style': fig_img.get('style', ''),
                        'has_caption': bool(fig_cap)
                    }
                    image_styles.append(img_info)
                
                if fig_cap:
                    caption_info = {
                        'text': fig_cap.get_text(),
                        'style': fig_cap.get('style', '')
                    }
                    figcaptions.append(caption_info)
            
            # 单独处理没有figure包裹的图片
            for img in images:
                # 检查是否已经在figure中处理过
                if not img.find_parent('figure'):
                    img_info = {
                        'src': img.get('src'),
                        'alt': img.get('alt', ''),
                        'width': img.get('width'),
                        'height': img.get('height'),
                        'style': img.get('style', ''),
                        'has_caption': False
                    }
                    image_styles.append(img_info)
            
            # 提取可能的图片标题（p标签紧跟在img后面的情况）
            for img in soup.find_all('img'):
                next_p = img.find_next_sibling('p')
                if next_p and next_p.get_text().strip():
                    # 简单判断是否可能是图片标题（比如以"图"、"Figure"开头）
                    text = next_p.get_text().strip()
                    if text.startswith(('图', 'Figure', 'Fig.')):
                        caption_info = {
                            'text': text,
                            'style': next_p.get('style', ''),
                            'is_sibling': True
                        }
                        figcaptions.append(caption_info)
            
            # 添加表格和图片标题样式到结果
            styles['table_styles'] = table_styles
            styles['image_styles'] = image_styles
            styles['figure_captions'] = figcaptions
            styles['content_stats'] = {
                'paragraphs': len(soup.find_all('p')),
                'tables': len(tables),
                'images': len(images),
                'figures': len(figures),
                'captions': len(figcaptions),
                'headings': sum(len(soup.find_all(f'h{i}')) for i in range(1, 7))
            }
            
            self.logger.info(f"成功抽取样式，包含表格和图片标题样式")
            return styles
            
        except Exception as e:
            self.logger.error(f"抽取样式失败: {str(e)}")
            raise
    
    def extract_docx_info(self, docx_path: str) -> Dict[str, Any]:
        """提取Word文档的元信息和基础格式信息"""
        try:
            # 使用pandoc提取文档元信息
            meta_output = self.temp_dir / f"meta_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            
            cmd = [
                self.pandoc_path,
                docx_path,
                '-o', str(meta_output),
                '--standalone',
                '--json'
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True)
            if result.returncode == 0 and meta_output.exists():
                with open(meta_output, 'r', encoding='utf-8') as f:
                    metadata = json.load(f)
                return metadata
            
            return {}
            
        except Exception as e:
            self.logger.warning(f"提取文档元信息失败: {str(e)}")
            return {}
    
    def parse_styles_from_html(self, html_path: Path) -> Dict[str, Any]:
        """从HTML文件中解析样式信息"""
        try:
            import re
            from bs4 import BeautifulSoup
            
            with open(html_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            soup = BeautifulSoup(content, 'html.parser')
            
            styles = {
                'css_styles': [],
                'heading_styles': {},
                'paragraph_styles': {},
                'font_families': set(),
                'font_sizes': set(),
                'colors': set()
            }
            
            # 提取CSS样式
            style_tags = soup.find_all('style')
            for style_tag in style_tags:
                if style_tag.string:
                    styles['css_styles'].append(style_tag.string)
            
            # 分析段落和标题样式
            for tag in soup.find_all(['p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'div', 'span']):
                style_attr = tag.get('style', '')
                class_attr = tag.get('class', [])
                
                if style_attr:
                    font_match = re.search(r'font-family:\s*([^;]+)', style_attr)
                    if font_match:
                        styles['font_families'].add(font_match.group(1).strip())
                    
                    size_match = re.search(r'font-size:\s*([^;]+)', style_attr)
                    if size_match:
                        styles['font_sizes'].add(size_match.group(1).strip())
                    
                    color_match = re.search(r'color:\s*([^;]+)', style_attr)
                    if color_match:
                        styles['colors'].add(color_match.group(1).strip())
                
                # 记录标题样式
                if tag.name in ['h1', 'h2', 'h3', 'h4', 'h5', 'h6']:
                    styles['heading_styles'][tag.name] = {
                        'style': style_attr,
                        'classes': class_attr
                    }
            
            # 转换set为list以便JSON序列化
            styles['font_families'] = list(styles['font_families'])
            styles['font_sizes'] = list(styles['font_sizes'])
            styles['colors'] = list(styles['colors'])
            
            return styles
            
        except ImportError:
            self.logger.warning("BeautifulSoup4未安装，使用基础样式提取")
            return self.parse_styles_basic(html_path)
        except Exception as e:
            self.logger.error(f"解析HTML样式失败: {str(e)}")
            return self.parse_styles_basic(html_path)
    
    def parse_styles_basic(self, html_path: Path) -> Dict[str, Any]:
        """基础HTML样式解析（不依赖BeautifulSoup）"""
        try:
            import re
            
            with open(html_path, 'r', encoding='utf-8') as f:
                content = f.read()
            
            styles = {
                'css_styles': [],
                'heading_styles': {},
                'font_families': [],
                'font_sizes': [],
                'colors': []
            }
            
            # 提取style标签内容
            style_matches = re.findall(r'<style[^>]*>(.*?)</style>', content, re.DOTALL)
            styles['css_styles'] = style_matches
            
            # 提取字体信息
            font_families = re.findall(r'font-family:\s*([^;]+)', content)
            styles['font_families'] = list(set([f.strip() for f in font_families]))
            
            font_sizes = re.findall(r'font-size:\s*([^;]+)', content)
            styles['font_sizes'] = list(set([s.strip() for s in font_sizes]))
            
            colors = re.findall(r'color:\s*([^;]+)', content)
            styles['colors'] = list(set([c.strip() for c in colors]))
            
            return styles
            
        except Exception as e:
            self.logger.error(f"基础样式解析失败: {str(e)}")
            return {'css_styles': [], 'heading_styles': {}, 'font_families': [], 'font_sizes': [], 'colors': []}
    
    def apply_styles_to_docx(self, source_styles: Dict[str, Any], target_docx_path: str, source_docx_path: str = None) -> Dict[str, Any]:
        """
        将源文档的样式应用到目标文档
        
        Args:
            source_styles: 源文档样式
            target_docx_path: 目标Word文档路径
            
        Returns:
            应用结果
        """
        try:
            self.logger.info(f"开始应用样式到文档: {target_docx_path}")
            
            # 验证文件格式
            if not target_docx_path.lower().endswith('.docx'):
                error_msg = f"不支持的文件格式: {target_docx_path}。请使用.docx格式的文档。"
                self.logger.error(error_msg)
                return {
                    'success': False,
                    'message': error_msg,
                    'timestamp': datetime.now().isoformat()
                }
            
            # 验证文件是否存在
            if not os.path.exists(target_docx_path):
                error_msg = f"文件不存在: {target_docx_path}"
                self.logger.error(error_msg)
                return {
                    'success': False,
                    'message': error_msg,
                    'timestamp': datetime.now().isoformat()
                }
            
            # 不再需要备份，因为我们创建新文件而不是修改原文件
            
            # 使用pandoc进行样式转换
            output_path = self.temp_dir / f"styled_{datetime.now().strftime('%Y%m%d_%H%M%S')}.docx"
            
            # 使用更直接的方法应用样式：使用Pandoc的引用文档功能
            # 这种方法可以更好地保留原始文档的样式结构
            
            # 检查是否提供了源文档路径
            if not source_docx_path:
                raise ValueError("应用样式需要提供源文档路径")
            
            # 1. 先将源文档转换为HTML，保留完整样式
            source_html = self.temp_dir / f"source_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
            source_cmd = [
                self.pandoc_path,
                source_docx_path,  # 使用提供的源文档路径
                '-o', str(source_html),
                '--standalone',
                '--toc',
                '--wrap=preserve'
            ]
            source_result = subprocess.run(source_cmd, capture_output=True, text=True)
            if source_result.returncode != 0:
                raise Exception(f"转换源文档失败: {source_result.stderr}")
            
            # 从源HTML提取样式并生成CSS，特别优化了表格和图片标题样式的提取
            css_temp = self.temp_dir / f"styles_{datetime.now().strftime('%Y%m%d_%H%M%S')}.css"
            
            # 使用更直接的方法提取样式：直接从源文档中提取样式信息
            # 创建一个更详细的CSS，专门针对表格和图片标题样式
            css_content = """
/* 重要：使用Pandoc引用文档功能时，以下CSS会与引用文档的样式结合 */

/* 表格样式 - 更详细的规则以确保表格格式正确 */
/* 表格整体样式 */
table { 
    border-collapse: collapse; 
    width: 100%; 
    margin: 2em 0; 
    font-family: inherit;
    font-size: inherit;
}

/* 表头样式 */
th { 
    border: 1px solid #000; 
    padding: 10px;
    background-color: #f2f2f2;
    font-weight: bold;
    text-align: center;
    vertical-align: middle;
}

/* 表格单元格样式 */
td { 
    border: 1px solid #000; 
    padding: 8px;
    text-align: left;
    vertical-align: top;
}

/* 确保表格行样式 */
tr { 
    page-break-inside: avoid;
}

/* 斑马纹样式 - 保持与源文档一致 */
tr:nth-child(even) { 
    background-color: transparent;
}

/* 图片和图片标题样式 - 特别优化 */
figure {
    margin: 2em 0;
    text-align: center;
    page-break-inside: avoid;
}

/* 确保图片不超出页面 */
img {
    max-width: 100%;
    height: auto;
    border: none;
    margin: 0 auto;
}

/* 图片标题样式 - 关键改进部分 */
figcaption {
    font-style: italic;
    font-size: 1em;
    margin-top: 0.8em;
    margin-bottom: 0.5em;
    color: #000;
    text-align: center;
    font-family: inherit;
    page-break-after: avoid;
}

/* 可能以p标签形式存在的图片标题 */
p.caption, p.figcaption {
    font-style: italic;
    font-size: 1em;
    text-align: center;
    color: #000;
    font-family: inherit;
    margin-top: 0.5em;
    margin-bottom: 1.5em;
}

/* 标题样式规则 */
h1, h2, h3, h4, h5, h6 {
    color: #000;
    font-weight: bold;
    margin-top: 1.5em;
    margin-bottom: 0.8em;
    font-family: inherit;
    page-break-after: avoid;
}

h1 { font-size: 2em; }
h2 { font-size: 1.75em; }
h3 { font-size: 1.5em; }
h4 { font-size: 1.25em; }
h5 { font-size: 1.1em; }
h6 { font-size: 1em; }

/* 正文样式规则 */
body {
    font-family: 'Times New Roman', serif;
    font-size: 12pt;
    line-height: 1.6;
    color: #000;
    margin: 0;
    padding: 0;
}

p {
    margin-bottom: 1em;
    text-indent: 2em;
    text-align: justify;
}

/* 文档结构样式 */
div, span {
    font-family: inherit;
    font-size: inherit;
    line-height: inherit;
}

/* 确保表格中的文本样式正确 */
table p {
    text-indent: 0;
    margin-bottom: 0.5em;
}

/* 确保引用样式 */
blockquote {
    border-left: 4px solid #ccc;
    margin: 1.5em 0;
    padding: 0.5em 1em;
    font-style: italic;
}

/* 列表样式 */
ul, ol {
    margin: 1em 0;
    padding-left: 2em;
}

li {
    margin-bottom: 0.5em;
}

/* 代码块样式 */
pre, code {
    font-family: 'Courier New', monospace;
    background-color: #f5f5f5;
    border-radius: 3px;
    padding: 0.2em 0.4em;
}

pre {
    padding: 1em;
    overflow: auto;
}
"""            
            # 保存CSS文件
            with open(css_temp, 'w', encoding='utf-8') as f:
                f.write(css_content)
            
            # 3. 转换目标文档为HTML，然后应用CSS样式再转回docx
            target_html = self.temp_dir / f"target_{datetime.now().strftime('%Y%m%d_%H%M%S')}.html"
            
            # 创建媒体文件提取目录
            media_dir = self.temp_dir / 'media'
            media_dir.mkdir(exist_ok=True)
            
            # 转换目标文档为HTML，提取媒体文件以保留图片
            html_cmd = [
                self.pandoc_path,
                target_docx_path,
                '-o', str(target_html),
                '--from', 'docx',
                '--to', 'html',
                '--standalone',
                '--wrap=preserve',
                '--extract-media', str(media_dir)  # 提取媒体文件
            ]
            
            html_result = subprocess.run(html_cmd, capture_output=True, text=True)
            if html_result.returncode != 0:
                raise Exception(f"转换目标文档为HTML失败: {html_result.stderr}")
            
            # 4. 从HTML转换回docx，同时应用CSS样式，保留图片和表格格式
            # 关键优化：移除可能干扰样式应用的参数，专注于表格和图片标题样式
            cmd = [
                self.pandoc_path,
                str(target_html),
                '-o', str(output_path),
                '--from', 'html',
                '--to', 'docx',
                '--css', str(css_temp),
                '--reference-doc', source_docx_path,  # 使用源文档作为引用文档
                '--resource-path', str(media_dir),  # 指定资源路径以保留图片
                '--strip-comments',  # 移除注释以减少干扰
                '--wrap=preserve',  # 保留换行以保持格式
                '--dpi=300',  # 确保图片分辨率
                '--extract-media', str(media_dir)  # 再次确保媒体文件被正确处理
            ]
            
            result = subprocess.run(cmd, capture_output=True, text=True)
            
            if result.returncode == 0 and output_path.exists():
                # 创建新文件而不是覆盖原始文件
                # 获取原始文件的目录和文件名
                target_dir = os.path.dirname(target_docx_path)
                target_filename = os.path.basename(target_docx_path)
                # 创建新文件名，添加_style_applied后缀
                name_without_ext, ext = os.path.splitext(target_filename)
                new_filename = f"{name_without_ext}_style_applied{ext}"
                new_file_path = os.path.join(target_dir, new_filename)
                
                # 移动临时文件到新路径
                shutil.move(str(output_path), new_file_path)
                
                result_data = {
                    'success': True,
                    'message': f'样式应用成功，新文件已保存到: {new_file_path}',
                    'output_path': new_file_path,  # 添加输出文件路径信息
                    'applied_styles': {
                        'font_families': len(source_styles.get('font_families', [])),
                        'font_sizes': len(source_styles.get('font_sizes', [])),
                        'colors': len(source_styles.get('colors', [])),
                        'css_rules': len(source_styles.get('css_styles', []))
                    },
                    'timestamp': datetime.now().isoformat()
                }
            else:
                result_data = {
                    'success': False,
                    'message': f'样式应用失败: {result.stderr}',
                    'timestamp': datetime.now().isoformat()
                }
            
            self.apply_results[target_docx_path] = result_data
            self.logger.info(f"样式应用{'成功' if result_data['success'] else '失败'}")
            return result_data
            
        except Exception as e:
            self.logger.error(f"应用样式失败: {str(e)}")
            error_result = {
                'success': False,
                'message': f'应用样式时发生错误: {str(e)}',
                'timestamp': datetime.now().isoformat()
            }
            self.apply_results[target_docx_path] = error_result
            return error_result
    
    def create_style_config(self, styles: Dict[str, Any]) -> Dict[str, Any]:
        """创建样式配置"""
        config = {
            'metadata': {
                'created_by': 'MiniMax Word Style Copier',
                'version': '1.0',
                'timestamp': datetime.now().isoformat()
            },
            'fonts': {
                'families': styles.get('font_families', []),
                'sizes': styles.get('font_sizes', [])
            },
            'colors': styles.get('colors', []),
            'styles': styles.get('css_styles', [])
        }
        return config
    
    # 注意：generate_css_file方法已被集成到apply_styles_to_docx中，这里不再需要单独的方法
    
    def batch_extract_styles(self, docx_files: List[str]) -> Dict[str, Dict[str, Any]]:
        """
        批量抽取多个文档的样式
        
        Args:
            docx_files: Word文档路径列表
            
        Returns:
            文档样式字典
        """
        # 过滤有效的docx文件
        valid_files = []
        for docx_path in docx_files:
            if docx_path.lower().endswith('.docx') and os.path.exists(docx_path):
                valid_files.append(docx_path)
            else:
                self.logger.warning(f"跳过无效文件: {docx_path}")
        
        self.logger.info(f"开始批量抽取 {len(valid_files)} 个有效文档的样式")
        
        results = {}
        for i, docx_path in enumerate(valid_files, 1):
            try:
                self.logger.info(f"处理进度: {i}/{len(valid_files)} - {docx_path}")
                styles = self.extract_styles_from_docx(docx_path)
                results[docx_path] = styles
            except Exception as e:
                self.logger.error(f"处理文档 {docx_path} 失败: {str(e)}")
                results[docx_path] = {'error': str(e)}
        
        return results
    
    def batch_apply_styles(self, source_styles: Dict[str, Any], target_files: List[str], source_docx_path: str = None) -> Dict[str, Dict[str, Any]]:
        """
        批量应用样式到多个目标文档
        
        Args:
            source_styles: 源样式
            target_files: 目标文档路径列表
            
        Returns:
            应用结果字典
        """
        # 过滤有效的docx文件
        valid_files = []
        for target_path in target_files:
            if target_path.lower().endswith('.docx') and os.path.exists(target_path):
                valid_files.append(target_path)
            else:
                self.logger.warning(f"跳过无效文件: {target_path}")
        
        self.logger.info(f"开始批量应用样式到 {len(valid_files)} 个有效文档")
        
        results = {}
        for i, target_path in enumerate(valid_files, 1):
            try:
                self.logger.info(f"处理进度: {i}/{len(valid_files)} - {target_path}")
                result = self.apply_styles_to_docx(source_styles, target_path, source_docx_path)
                results[target_path] = result
            except Exception as e:
                self.logger.error(f"处理文档 {target_path} 失败: {str(e)}")
                results[target_path] = {'success': False, 'message': str(e)}
        
        return results
    
    def generate_report(self, results: Dict[str, Any]) -> str:
        """
        生成样式应用报告
        
        Args:
            results: 应用结果
            
        Returns:
            格式化的报告
        """
        report_lines = [
            "# Word样式复制器执行报告",
            f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
            "",
            "## 概览",
            f"- 总处理文档数: {len(results)}",
            f"- 成功应用: {sum(1 for r in results.values() if r.get('success', False))}",
            f"- 失败数量: {sum(1 for r in results.values() if not r.get('success', True))}",
            "",
            "## 详细结果"
        ]
        
        for doc_path, result in results.items():
            report_lines.extend([
                f"### {os.path.basename(doc_path)}",
                f"路径: `{doc_path}`",
                f"状态: {'✅ 成功' if result.get('success', False) else '❌ 失败'}",
            ])
            
            if result.get('success', False):
                applied_styles = result.get('applied_styles', {})
                report_lines.extend([
                    "应用样式统计:",
                    f"- 字体家族: {applied_styles.get('font_families', 0)} 种",
                    f"- 字体大小: {applied_styles.get('font_sizes', 0)} 种", 
                    f"- 颜色: {applied_styles.get('colors', 0)} 种",
                    f"- CSS规则: {applied_styles.get('css_rules', 0)} 条"
                ])
                
                if 'backup_path' in result:
                    report_lines.append(f"备份文件: `{result['backup_path']}'")
            else:
                report_lines.append(f"错误信息: {result.get('message', '未知错误')}")
            
            report_lines.append("")
        
        report_lines.extend([
            "## 说明",
            "- 成功应用的文档会保留原始备份",
            "- 如需恢复原始格式，请使用备份文件替换",
            "- 样式应用基于Pandoc转换，可能存在格式差异",
            ""
        ])
        
        return "\n".join(report_lines)
    
    def interactive_mode(self):
        """交互式模式"""
        print("=" * 60)
        print("🔧 智能Word样式复制器 - 交互式模式")
        print("=" * 60)
        
        while True:
            print("\n请选择操作:")
            print("1. 抽取单个文档样式")
            print("2. 批量抽取文档样式")
            print("3. 应用样式到单个文档")
            print("4. 批量应用样式")
            print("5. 查看样式分析")
            print("6. 生成执行报告")
            print("7. 退出")
            
            choice = input("\n请输入选项 (1-7): ").strip()
            
            if choice == '1':
                self.handle_single_extract()
            elif choice == '2':
                self.handle_batch_extract()
            elif choice == '3':
                self.handle_single_apply()
            elif choice == '4':
                self.handle_batch_apply()
            elif choice == '5':
                self.handle_style_analysis()
            elif choice == '6':
                self.handle_report_generation()
            elif choice == '7':
                print("感谢使用智能Word样式复制器！")
                break
            else:
                print("无效选项，请重新选择")
    
    def handle_single_extract(self):
        """处理单个文档样式抽取"""
        docx_path = input("请输入Word文档路径: ").strip()
        
        # 预先验证文件格式
        if not docx_path.lower().endswith('.docx'):
            print("❌ 不支持的文件格式，请使用.docx格式的文档")
            return
        
        if not os.path.exists(docx_path):
            print("❌ 文件不存在")
            return
        
        try:
            styles = self.extract_styles_from_docx(docx_path)
            
            # 保存样式文件
            output_file = f"styles_{os.path.splitext(os.path.basename(docx_path))[0]}.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(styles, f, indent=2, ensure_ascii=False)
            
            print(f"✅ 样式抽取成功")
            print(f"📁 样式文件已保存: {output_file}")
            print(f"📊 抽取统计:")
            print(f"   - 字体家族: {len(styles.get('font_families', []))} 种")
            print(f"   - 字体大小: {len(styles.get('font_sizes', []))} 种")
            print(f"   - 颜色: {len(styles.get('colors', []))} 种")
            
        except Exception as e:
            print(f"❌ 抽取失败: {str(e)}")
    
    def handle_batch_extract(self):
        """处理批量文档样式抽取"""
        print("请输入文档路径（每行一个，回车结束）:")
        docx_paths = []
        while True:
            path = input().strip()
            if not path:
                break
            if not path.lower().endswith('.docx'):
                print(f"❌ 不支持的文件格式: {path}，请使用.docx格式")
                continue
            if os.path.exists(path):
                docx_paths.append(path)
                print(f"✅ 已添加: {path}")
            else:
                print(f"❌ 文件不存在: {path}")
        
        if not docx_paths:
            print("❌ 没有有效的文档路径")
            return
        
        try:
            results = self.batch_extract_styles(docx_paths)
            
            # 保存批量结果
            output_file = f"batch_styles_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(results, f, indent=2, ensure_ascii=False)
            
            print(f"✅ 批量抽取完成")
            print(f"📁 结果文件: {output_file}")
            
        except Exception as e:
            print(f"❌ 批量抽取失败: {str(e)}")
    
    def handle_single_apply(self):
        """处理单个样式应用"""
        source_path = input("请输入样式源文档路径: ").strip()
        target_path = input("请输入目标文档路径: ").strip()
        
        # 预先验证文件格式
        if not source_path.lower().endswith('.docx'):
            print("❌ 源文档格式不支持，请使用.docx格式")
            return
        if not target_path.lower().endswith('.docx'):
            print("❌ 目标文档格式不支持，请使用.docx格式")
            return
        
        if not os.path.exists(source_path):
            print("❌ 源文档不存在")
            return
        if not os.path.exists(target_path):
            print("❌ 目标文档不存在")
            return
        
        try:
            styles = self.extract_styles_from_docx(source_path)
            result = self.apply_styles_to_docx(styles, target_path, source_path)
            
            if result['success']:
                print("✅ 样式应用成功")
                print(f"📁 备份文件: {result['backup_path']}")
            else:
                print(f"❌ 样式应用失败: {result['message']}")
                
        except Exception as e:
            print(f"❌ 应用失败: {str(e)}")
    
    def handle_batch_apply(self):
        """处理批量样式应用"""
        source_path = input("请输入样式源文档路径: ").strip()
        
        # 验证源文档格式
        if not source_path.lower().endswith('.docx'):
            print("❌ 源文档格式不支持，请使用.docx格式")
            return
        if not os.path.exists(source_path):
            print("❌ 源文档不存在")
            return
        
        print("请输入目标文档路径（每行一个，回车结束）:")
        target_paths = []
        while True:
            path = input().strip()
            if not path:
                break
            if not path.lower().endswith('.docx'):
                print(f"❌ 不支持的文件格式: {path}，请使用.docx格式")
                continue
            if os.path.exists(path):
                target_paths.append(path)
                print(f"✅ 已添加: {path}")
            else:
                print(f"❌ 文件不存在: {path}")
        
        if not target_paths:
            print("❌ 没有有效的目标文档路径")
            return
        
        try:
            styles = self.extract_styles_from_docx(source_path)
            results = self.batch_apply_styles(styles, target_paths, source_path)
            
            # 生成报告
            report = self.generate_report(results)
            report_file = f"batch_apply_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
            with open(report_file, 'w', encoding='utf-8') as f:
                f.write(report)
            
            print(f"✅ 批量应用完成")
            print(f"📁 报告文件: {report_file}")
            
        except Exception as e:
            print(f"❌ 批量应用失败: {str(e)}")
    
    def handle_style_analysis(self):
        """处理样式分析"""
        styles_file = input("请输入样式JSON文件路径: ").strip()
        
        if not os.path.exists(styles_file):
            print("❌ 样式文件不存在")
            return
        
        try:
            with open(styles_file, 'r', encoding='utf-8') as f:
                styles = json.load(f)
            
            print("\n📊 样式分析报告")
            print("-" * 40)
            
            fonts = styles.get('font_families', [])
            if fonts:
                print(f"字体家族 ({len(fonts)} 种):")
                for font in fonts[:10]:  # 显示前10种
                    print(f"  - {font}")
                if len(fonts) > 10:
                    print(f"  ... 还有 {len(fonts) - 10} 种")
            
            sizes = styles.get('font_sizes', [])
            if sizes:
                print(f"\n字体大小 ({len(sizes)} 种):")
                for size in sizes[:10]:
                    print(f"  - {size}")
                if len(sizes) > 10:
                    print(f"  ... 还有 {len(sizes) - 10} 种")
            
            colors = styles.get('colors', [])
            if colors:
                print(f"\n颜色 ({len(colors)} 种):")
                for color in colors[:10]:
                    print(f"  - {color}")
                if len(colors) > 10:
                    print(f"  ... 还有 {len(colors) - 10} 种")
            
        except Exception as e:
            print(f"❌ 分析失败: {str(e)}")
    
    def handle_report_generation(self):
        """处理报告生成"""
        if not self.apply_results:
            print("❌ 没有可用的执行结果")
            return
        
        report = self.generate_report(self.apply_results)
        report_file = f"style_copy_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.md"
        
        try:
            with open(report_file, 'w', encoding='utf-8') as f:
                f.write(report)
            print(f"✅ 报告生成成功: {report_file}")
        except Exception as e:
            print(f"❌ 报告生成失败: {str(e)}")
    
    def cleanup(self):
        """清理临时文件"""
        try:
            if os.path.exists(self.temp_dir):
                shutil.rmtree(self.temp_dir)
                self.logger.info("临时文件清理完成")
        except Exception as e:
            self.logger.warning(f"清理临时文件失败: {str(e)}")
    
    def __del__(self):
        """析构函数"""
        self.cleanup()

def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='智能Word样式复制器')
    parser.add_argument('--interactive', '-i', action='store_true', 
                       help='启动交互式模式')
    parser.add_argument('--extract', '-e', type=str, 
                       help='抽取指定文档的样式')
    parser.add_argument('--apply', '-a', type=str, nargs=2,
                       metavar=('SOURCE', 'TARGET'),
                       help='应用样式 [源文档] [目标文档]')
    parser.add_argument('--batch-extract', type=str, nargs='+',
                       help='批量抽取多个文档的样式')
    parser.add_argument('--batch-apply', type=str, nargs='+',
                       help='批量应用样式到多个文档')
    parser.add_argument('--output', '-o', type=str,
                       help='输出文件路径')
    
    args = parser.parse_args()
    
    copier = WordStyleCopier()
    
    try:
        if args.interactive or (not any(vars(args).values())):
            copier.interactive_mode()
        elif args.extract:
            styles = copier.extract_styles_from_docx(args.extract)
            output_file = args.output or f"styles_{os.path.splitext(os.path.basename(args.extract))[0]}.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(styles, f, indent=2, ensure_ascii=False)
            print(f"样式已保存到: {output_file}")
        elif args.apply:
            # 验证命令行参数中的文件格式
            if not args.apply[0].lower().endswith('.docx'):
                print("错误: 源文档必须是.docx格式")
                sys.exit(1)
            if not args.apply[1].lower().endswith('.docx'):
                print("错误: 目标文档必须是.docx格式")
                sys.exit(1)
            
            styles = copier.extract_styles_from_docx(args.apply[0])
            result = copier.apply_styles_to_docx(styles, args.apply[1], args.apply[0])
            print(f"应用结果: {result['message']}")
        elif args.batch_extract:
            # 验证命令行参数中的文件格式
            for docx_path in args.batch_extract:
                if not docx_path.lower().endswith('.docx'):
                    print(f"错误: 文档 {docx_path} 必须是.docx格式")
                    sys.exit(1)
                    
            results = copier.batch_extract_styles(args.batch_extract)
            output_file = args.output or f"batch_styles_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(results, f, indent=2, ensure_ascii=False)
            print(f"批量抽取结果已保存到: {output_file}")
        elif args.batch_apply:
            # 验证命令行参数中的源文件格式
            if not args.batch_apply[0].lower().endswith('.docx'):
                print("错误: 源文档必须是.docx格式")
                sys.exit(1)
            
            source_styles = copier.extract_styles_from_docx(args.batch_apply[0])
            targets = args.batch_apply[1:]
            results = copier.batch_apply_styles(source_styles, targets, args.batch_apply[0])
            report = copier.generate_report(results)
            if args.output:
                with open(args.output, 'w', encoding='utf-8') as f:
                    f.write(report)
            else:
                print(report)
    
    except Exception as e:
        print(f"错误: {str(e)}")
        sys.exit(1)
    finally:
        copier.cleanup()

if __name__ == "__main__":
    main()